import time
import logging
import logging.handlers
from datetime import datetime, timezone, timedelta
from kubernetes import client, config

# 全局日志记录器
logger = logging.getLogger('k8s_event_monitor')

# 设置上海时区
SHANGHAI_TZ = timezone(timedelta(hours=8))


def setup_logging(log_to_file=False, log_file='k8s-events.log', max_bytes=1024 * 1024 * 1024, backup_count=5):
    """配置日志记录器"""
    # 清除之前的处理器
    for handler in logger.handlers[:]:
        logger.removeHandler(handler)
        handler.close()

    # 设置日志级别
    logger.setLevel(logging.INFO)

    # 创建自定义Formatter，使用上海时区
    class ShanghaiTimeFormatter(logging.Formatter):
        def formatTime(self, record, datefmt=None):
            dt = datetime.fromtimestamp(record.created, SHANGHAI_TZ)
            if datefmt:
                return dt.strftime(datefmt)
            return dt.strftime("%Y-%m-%d %H:%M:%S,%f")[:-3]

    # 创建格式化器
    formatter = ShanghaiTimeFormatter(
        '%(asctime)s - %(levelname)s - %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S'
    )

    # 控制台处理器
    console_handler = logging.StreamHandler()
    console_handler.setFormatter(formatter)
    logger.addHandler(console_handler)

    # 文件处理器（如果启用）
    if log_to_file:
        # 使用RotatingFileHandler实现日志轮转
        file_handler = logging.handlers.RotatingFileHandler(
            log_file,
            maxBytes=max_bytes,  # 10MB
            backupCount=backup_count  # 保留5个备份
        )
        file_handler.setFormatter(formatter)
        logger.addHandler(file_handler)

    return logger


def get_recent_events(interval_minutes=1, namespace=None, log_to_file=False):
    """
    定时获取Kubernetes事件信息
    :param interval_minutes: 获取间隔时间(分钟)
    :param namespace: 指定命名空间，None表示所有命名空间
    :param log_to_file: 是否将日志写入文件
    """
    # 配置日志
    setup_logging(log_to_file)

    # 加载kube配置
    # try:
    #     config.load_kube_config(config_file="kube/config")
    # except:
    #     config.load_incluster_config()

    # 在k8s集群内使用ServiceAccount认证
    try:
        logger.info("Attempt to use ServiceAccount authentication within the cluster...")
        config.load_incluster_config()
        logger.info("Successfully loaded ServiceAccount authentication!!!")
    except Exception as e:
        logger.error(f"Failed to load ServiceAccount authentication: {str(e)}")
        logger.info("Attempt to load the kubeconfig configuration")
        try:
            config.load_kube_config(config_file="kube/config")
            logger.info("Successfully loaded kubeconfig configuration...")
        except Exception as e:
            logger.error(f"Failed to load kubeconfig: {str(e)}")
            logger.error("Unable to connect to the Kubernetes cluster, program exits!!!")
            return

    v1 = client.CoreV1Api()
    last_check_time = datetime.utcnow()

    # logger.info(f"开始定时获取Kubernetes事件，间隔{interval_minutes}分钟...")
    logger.info(f"Start to periodically fetch kubernetes events，with an interval of {interval_minutes} minute...")

    logger.info("=" * 100)

    while True:
        try:
            # 获取当前UTC时间和上海时间
            utc_now = datetime.utcnow()
            shanghai_now = datetime.now(SHANGHAI_TZ)

            # logger.info(f"\nCurrent Time(shanghai): {shanghai_now.strftime('%Y-%m-%d %H:%M:%S')}")
            # logger.info(f"Check The Time Range(UTC): {last_check_time} - {utc_now}")
            # logger.info("-" * 100)

            # 获取事件列表
            if namespace:
                events = v1.list_namespaced_event(namespace, timeout_seconds = 30)
            else:
                events = v1.list_event_for_all_namespaces(timeout_seconds = 30)

            # 筛选并打印最近interval_minutes分钟内的事件
            new_events = []
            for event in events.items:
                event_time = event.last_timestamp or event.event_time or event.metadata.creation_timestamp
                if event_time and event_time.replace(tzinfo=None) > last_check_time:
                    new_events.append(event)

            if not new_events:
                # logger.info("No new events found.")
                pass
            else:
                # 按时间排序
                new_events.sort(key=lambda e: (e.last_timestamp or e.event_time or e.metadata.creation_timestamp))
                for event in new_events:
                    print_event(event)

            # 更新最后检查时间并等待下一个周期
            last_check_time = utc_now
            time.sleep(interval_minutes * 60)

        except Exception as e:
            logger.error(f"Error occurred while retrieving the events: {str(e)}")
            time.sleep(30)  # 出错后等待30秒再重试


def print_event(event):
    """格式化打印事件信息，时间转换为上海时区"""
    event_time = event.last_timestamp or event.event_time or event.metadata.creation_timestamp
    event_start_time = event.first_timestamp
    if event_time:
        # 将UTC时间转换为上海时区
        utc_time = event_time.replace(tzinfo=timezone.utc)
        shanghai_time = utc_time.astimezone(SHANGHAI_TZ)
        formatted_time = shanghai_time.strftime("%Y-%m-%d %H:%M:%S")
    else:
        formatted_time = "Unknown"
    if event.metadata.namespace:
        utc_start_time = event_start_time.replace(tzinfo=timezone.utc)
        shanghai_start_time = utc_start_time.astimezone(SHANGHAI_TZ)
        formatted_start_time = shanghai_start_time.strftime("%Y-%m-%d %H:%M:%S")
    else:
        formatted_start_time = "Unknown"

    event_counts = f"{event.count}"    #事件通报的次数
    obj_ref = f"{event.involved_object.kind}/{event.involved_object.name}" if event.involved_object else "Unknown"
    # message = f"{formatted_time} {event.type:7} {event.reason:20} {obj_ref:30} {event.message}"
    message = f"{event_start_time}---{formatted_time} {event.type:10} {event.reason:20}  counts:{event_counts:10}  {obj_ref:30} {event.message}"
    logger.info(message)


if __name__ == "__main__":
    # 每隔1分钟检查一次，可以调整interval_minutes参数
    # 可以指定namespace如namespace="default"
    # 启用文件日志：设置log_to_file=True
    get_recent_events(
        interval_minutes=1,
        namespace=None,
        log_to_file=True  # 设置为True启用文件日志和轮转
    )